package at.evonfc.db;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;

import android.util.Log;
import at.evonfc.bl.DateUtils;
import at.evonfc.data.Rental;
import at.evonfc.data.Device;
import at.evonfc.data.Equipment;
import at.evonfc.view.MainActivity;

public class DataBaseAccess {

	public static final String SERVER_EVO = "http://inventory.evolaris.net:81/AppToServer/";
	public static final String SERVER_AD = "http://192.168.0.71/AppToServer/";
	public static final String SERVER = SERVER_AD;
	
	private static InputStream getStreamVonFile(String file, Map<String, String> params) {
		// http post
		InputStream is = null;
		try {
			//create the param string
			StringBuilder paramString = new StringBuilder();
			if(params != null) {
				//check if it is the first run to add no '&' before the actual string
				boolean firstRun = true;
				paramString.append("?");
				for(Entry<String, String> param : params.entrySet()) {
					//append the key and the value
					if(firstRun) {
						paramString.append(param.getKey()+"="+param.getValue());
						firstRun = false;
					} else {
						paramString.append("&"+param.getKey()+"="+param.getValue());
					}
				}
			}
			Log.v("url", SERVER+file+paramString.toString());
			//open connection
			HttpClient httpclient = new DefaultHttpClient();
			HttpPost httppost = new HttpPost(
					SERVER+file+paramString.toString());
			HttpResponse response = httpclient.execute(httppost);
			HttpEntity entity = response.getEntity();
			//set the input stream
			is = entity.getContent();
		} catch (Exception e) {
			Log.e("log_tag", "Error in http connection " + e.toString());
		}
		return is;
	}
	
	private static String getDataFromStream(InputStream is) {
		String result = null;
		try {
			//create a reader from the input stream
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					is, "UTF-8"), 8);
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			//close the input stream
			reader.close();

			if(!sb.toString().isEmpty()) {
				result = sb.toString();
			}
		} catch (Exception e) {
			Log.v("log_tag", "Error converting result " + e.toString());
		}
		return result;
	}
	
	public static String getUserName(String id) {
		String result = DBSession.getUserName(id);
		if(result != null) {
			return result;
		}
		Map<String, String> params = new HashMap<String, String>();
		params.put("user", id+"");
		InputStream is = getStreamVonFile("login_AD.php", params);
		// convert response to string
		result = getDataFromStream(is);
		if(result != null && !result.isEmpty()) {
			DBSession.addUser(id, result);
		}
		return result;
	}
	
	public static Device getDevice(int id) {
		Device dev = DBSession.getDevice(id);
		if(dev != null) {
			return dev;
		}
		Map<String, String> params = new HashMap<String, String>();
		params.put("device", id+"");
		InputStream is = getStreamVonFile("getDevices.php", params);
		String result = getDataFromStream(is);
		String[] deviceDataParts = result.split(";");
		String name = deviceDataParts[1];
		int maxBorrowDate = Integer.parseInt(deviceDataParts[2]);
		ArrayList<String> properties = new ArrayList<String>();
		if(deviceDataParts.length > 3) {
			if(!deviceDataParts[3].isEmpty()) {
				String[] propertiesParts = deviceDataParts[3].split(",");
				for(String prop : propertiesParts) {
					properties.add(prop.trim());
				}
			}
		}
		ArrayList<Equipment> availableEquipment = new ArrayList<Equipment>();
		if(deviceDataParts.length > 4) {
			if(!deviceDataParts[4].isEmpty()) {
				String[] eqipmentParts = deviceDataParts[4].split(",");
				for(String eq : eqipmentParts) {
					String[] eqParts = eq.split(":");
					availableEquipment.add(new Equipment(Integer.parseInt(eqParts[0].trim()), eqParts[1].trim()));
				}
			}
		}
		dev = new Device(id, name, maxBorrowDate, properties, availableEquipment);
		DBSession.addObject(dev);
		return dev;
	}
	
	
	
	public static void borrowDevice(int deviceID, String userID, Calendar endDate, List<Equipment> equipments) {
		Calendar now = Calendar.getInstance();
		String startDate = DateUtils.getInstance().convertToDatabaseString(now); 
		String newEndDate = null;
		Log.v("enddate", endDate+"   --- ");
		if(endDate != null) {
			newEndDate = DateUtils.getInstance().convertToDatabaseString(endDate);
		} else {
			newEndDate = "null";
		}
		Map<String, String> params = new HashMap<String, String>();
		params.put("employee", userID);
		params.put("begindate", startDate+"");
		params.put("enddate", newEndDate+"");
		params.put("device", deviceID+"");
		InputStream is = getStreamVonFile("borrowDevices.php", params);
		String result = getDataFromStream(is);
		Log.v("res borrow", result);
		if(result.startsWith("success")) {
			if(equipments != null) {
				for(Equipment eq : equipments) {
					borrowEquipment(eq.getEquipmentId(), userID);
				}
			}
		}
	}
	
	public static void reserveDevice(int deviceID, String userID, Calendar startDate, Calendar endDate, List<Equipment> equipments) {
		String newStartDate = DateUtils.getInstance().convertToDatabaseString(startDate);
		String newEndDate = null;
		if(endDate != null) {
			newEndDate = DateUtils.getInstance().convertToDatabaseString(endDate);
		} else {
			newEndDate = "null";
		}
		Map<String, String> params = new HashMap<String, String>();
		params.put("employee", userID+"");
		params.put("begindate", newStartDate+"");
		params.put("enddate", newEndDate+"");
		params.put("device", deviceID+"");
		InputStream is = getStreamVonFile("borrowDevices.php", params);
		String result = getDataFromStream(is);
		if(result.startsWith("success")) {
			if(equipments != null) {
				for(Equipment eq : equipments) {
					borrowEquipment(eq.getEquipmentId(), userID);
					Log.v("borrow eq", "borrow");
				}
			}
		}
	}
	
	private static void borrowEquipment(int equipmentID, String userID) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("equipment", equipmentID+"");
		params.put("employee", userID+"");
		InputStream is = getStreamVonFile("borrowEquipment.php", params);
		String result = getDataFromStream(is);
	}

	public static void returnDevice(int id, String user) {
		
		Map<String, String> params = new HashMap<String, String>();
		params.put("device", id+"");
		params.put("user", user);
		InputStream is = getStreamVonFile("handBackDevices.php", params);
		String result = getDataFromStream(is);
	}
	
	public static List<Rental> getDevicesFromUser(String userid) throws Exception {
		List<Rental> devices = new ArrayList<Rental>();
		
		Map<String, String> params = new HashMap<String, String>();
		params.put("user", userid);
		InputStream is = getStreamVonFile("getBorrowedDevices.php", params);
		String result = getDataFromStream(is);

		String[] resultParts = result.split(";");
		for(String sDevice : resultParts) {
			String[] deviceStringParts = sDevice.split(",");
			if(deviceStringParts.length > 1) {
				int deviceID = Integer.parseInt(deviceStringParts[0].trim());
				Device device = getDevice(deviceID);
				String beginDate = deviceStringParts[1];

				Rental dev;
				if(deviceStringParts.length < 3) {
					dev = new Rental(device, DateUtils.getInstance().convertToCalendar(beginDate), null, getUserName(userid));
				} else {
					String endDate = deviceStringParts[2];
					dev = new Rental(device, DateUtils.getInstance().convertToCalendar(beginDate), DateUtils.getInstance().convertToCalendar(endDate), getUserName(userid));
				}
				devices.add(dev);
			}
		}
		
		return devices;
	}
	
	public static List<String> getEquipmentFromBorrowedDevice(int deviceid) {
		List<String> equipments = new ArrayList<String>();
		
		Map<String, String> params = new HashMap<String, String>();
		params.put("device", deviceid+"");
		InputStream is = getStreamVonFile("getEquipmentToBorrowedDevice.php", params);
		String result = getDataFromStream(is);
		
		if(result != null) {
			String[] resultParts = result.split(",");
			for(String eq : resultParts) {
				if(!eq.isEmpty()) {
					equipments.add(eq);
				}
			}
		}
		
		return equipments;
	}
	
	public static List<Rental> getAllRentalsFromDevice(int deviceID) {
		List<Rental> rentals = new ArrayList<Rental>();
		
		Map<String, String> params = new HashMap<String, String>();
		params.put("device", deviceID+"");
		
		InputStream is = getStreamVonFile("checkReserves.php", params);
		String result = getDataFromStream(is);
		
		if(result != null) {
			String[] resultParts = result.split(";");
			for(String sDates : resultParts) {
				String sDateParts[] = sDates.trim().split(",");
				String emp = getUserName(sDateParts[0]);
				if(sDateParts.length > 2) {
					Calendar startDate = DateUtils.getInstance().convertToCalendar(sDateParts[1].trim());
					Calendar endDate = DateUtils.getInstance().convertToCalendar(sDateParts[2].trim());
					rentals.add(new Rental(getDevice(deviceID), startDate, endDate, emp));
				} else {
					Calendar startDate = DateUtils.getInstance().convertToCalendar(sDateParts[1].trim());
					rentals.add(new Rental(getDevice(deviceID), startDate, null, emp));
				}
			}
		}
		
		return rentals;
	}
	
	public static boolean isDeviceAvailableForDate(int deviceID, Calendar date) {
		boolean availbale = false;
		
		Map<String, String> params = new HashMap<String, String>();
		params.put("device", deviceID+"");
		params.put("date", DateUtils.getInstance().convertToDatabaseString(date)+"");
		
		InputStream is = getStreamVonFile("checkDeviceAvailable.php", params);
		String result = getDataFromStream(is);
		
		//true means available
		availbale = result.startsWith("t");
		
		return availbale;
	}
}
